package com.tanhua.server.interceptor;

import cn.hutool.core.convert.Convert;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tanhua.server.utils.Cache;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.MethodParameter;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.concurrent.TimeUnit;

@ControllerAdvice
@Slf4j
public class MyResponseBodyAdvice implements ResponseBodyAdvice {

    @Value("${tanhua.cache.enable}")
    private Boolean cacheEnable;

    @Autowired
    private StringRedisTemplate redisTemplate;

    private static final ObjectMapper MAPPER = new ObjectMapper();

    /**
     * 需要写入缓存的条件：总开关开启、包含了@Cache注解、是GET请求
     *
     * @param methodParameter
     * @param aClass
     * @return
     */
    @Override
    public boolean supports(MethodParameter methodParameter, Class aClass) {
        return cacheEnable && methodParameter.hasMethodAnnotation(Cache.class)
                && methodParameter.hasMethodAnnotation(GetMapping.class);
    }

    @Override
    public Object beforeBodyWrite(Object result, MethodParameter methodParameter,
                                  MediaType mediaType, Class aClass,
                                  ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {

        if (null == result) {
            // 如果Controller中返回null，不进行处理
            return null;
        }

        String redisData;
        if (result instanceof String) {
            redisData = (String) result;
        } else {
            //将对象序列化成json
            // 使用hutool工具序列化时，会使用别名进行序列化，会导致与前端字段不同 效果没有办法正常显示
            // redisData = JSONUtil.toJsonStr(result);
            try {
                redisData = MAPPER.writeValueAsString(result);
            } catch (Exception e) {
                log.error("json序列化失败！result = {}", result.toString(), e);
                return result;
            }
        }

        String redisKey = RedisCacheInterceptor.createRedisKey(((ServletServerHttpRequest) serverHttpRequest).getServletRequest());
        //缓存时间
        Long time = Convert.toLong(methodParameter.getMethodAnnotation(Cache.class).time());
        //写入到缓存中
        this.redisTemplate.opsForValue().set(redisKey, redisData, time, TimeUnit.SECONDS);

        return result;
    }
}
